学习了 babel 的编译流程和 AST 之后,我们来学习下 babel 的 api,通过这些 api 来操作 AST,完成代码的转换。
注意,我们学习的 api 是 babel 7.x 的,babel 6 的 api 还没有按照 scope 来划分,是 babel-parser 这种,而 babel 7 变成了@babel/parser 这种。但具体 api 差不多,我们学的是一些原理性的东西,这些东西在版本迭代中是不会变的。
# babel 的 api 有哪些
我们知道 babel 的编译流程分为三步:parse、transform、generate,每一步都暴露了一些 api 出来。
- parse 阶段有
@babel/parser,功能是把源码转成 AST - transform 阶段有
@babel/traverse,可以遍历 AST,并调用 visitor 函数修改 AST,修改 AST 自然涉及到 AST 的判断、创建、修改等,这时候就需要@babel/types了,当需要批量创建 AST 的时候可以使用@babel/template来简化 AST 创建逻辑。 - generate 阶段会把 AST 打印为目标代码字符串,同时生成 sourcemap,需要
@babel/generator包 - 中途遇到错误想打印代码位置的时候,使用
@babel/code-frame包 - babel 的整体功能通过
@babel/core提供,基于上面的包完成 babel 整体的编译流程,并实现插件功能。
我们主要学习的就是 @babel/parser,@babel/traverse,@babel/generator,@babel/types,@babel/template 这五个包的 api 的使用。
# @babel/parser
babel parser 叫 babylon,是基于 acorn 实现的,扩展了很多语法,可以支持 es next(现在支持到 es2020)、jsx、flow、typescript 等语法的解析,其中 jsx、flow、typescript 这些非标准的语法的解析需要指定语法插件。
它提供了有两个 api:parse 和 parseExpression。两者都是把源码转成 AST,不过 parse 返回的 AST 根节点是 File(整个 AST),parseExpression 返回的 AST 根节点是是 Expression(表达式的 AST),粒度不同。
function parse(input: string, options?: ParserOptions): File
function parseExpression(input: string, options?: ParserOptions): Expression
详细的 options 可以查看文档。其实主要分为两类,一是 parse 的内容是什么,二是以什么方式去 parse
parse 的内容是什么:
plugins: 指定jsx、typescript、flow 等插件来解析对应的语法allowXxx: 指定一些语法是否允许,比如函数外的 await、没声明的 export等sourceType: 指定是否支持解析模块语法,有 module、script、unambiguous 3个取值,module 是解析 es module 语法,script 则不解析 es module 语法,当作脚本执行,unambiguous 则是根据内容是否有 import 和 export 来确定是否解析 es module 语法。
以什么方式 parse
strictMode是否是严格模式startLine从源码哪一行开始 parseerrorRecovery出错时是否记录错误并继续往下 parsetokensparse 的时候是否保留 token 信息ranges是否在 ast 节点中添加 ranges 属性
其实最常用的 option 就是 plugins、sourceType 这两个,比如要 parse tsx 模块,那么就可以这样来写
